home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_087
/
yaiffr
/
iff.c
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
7KB
|
307 lines
/* :ts=8 bk=0
*
* iff.c: A cheesy IFF ILBM reader.
*
* Leo L. Schwab 8705.11
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/view.h>
#include <stdio.h>
#include "myiff.h"
static struct ViewPort *viewport; /* Working viewport */
/*
* Okay, here's how this works. This routine assumes that the file
* descriptor points to just past the FORM type and size fields in the file.
* It returns a pointer to a ViewPort structure with all necessary
* substructures, suitable for MakeVPort()ing. It assumes someone else will
* know how to deallocate all said structures and resources. Fortunately,
* there's enough information in ViewPorts to be able to intelligently free
* anything they may use.
*/
struct ViewPort *
readform (fd, formsize)
FILE *fd; /* File descriptor */
long formsize; /* Size of this FORM */
{
struct BitMapHeader bmhd;
struct ChunkHeader ch;
long subtype;
register int i, n;
char gotheader = 0, gotcmap = 0, gotcamg = 0;
void *tmp;
if (!getsubtype (fd, &subtype))
return (NULL);
formsize -= sizeof (subtype);
if (subtype != ILBM) {
puts ("FORM not an ILBM, skipping...");
skipchunk (fd, formsize - sizeof (subtype));
return (NULL);
}
if (!(viewport = AllocMem ((long) sizeof (*viewport), MEMF_CLEAR)))
ackphft ("ViewPort allocation failed.");
InitVPort (viewport);
while (formsize > 0) {
if (!getchunkheader (fd, &ch))
ackphft ("Malformed IFF FORM.");
formsize -= sizeof (ch);
switch (ch.TYPE) {
case BMHD: {
register struct BitMap *bm;
register struct RasInfo *ri;
fread (&bmhd, (int) ch.chunksize, 1, fd);
if (!(bm = AllocMem ((long) sizeof (*bm),
MEMF_CLEAR)))
ackphft ("BitMap allocation failed.");
InitBitMap (bm,
(long) bmhd.nplanes,
(long) bmhd.w, (long) bmhd.h);
if (!(ri = AllocMem ((long) sizeof (*ri),
MEMF_CLEAR)))
ackphft ("RasInfo allocation failed.");
ri -> BitMap = bm;
ri -> RxOffset = ri -> RyOffset = NULL;
ri -> Next = NULL;
viewport -> DWidth = bmhd.w;
viewport -> DHeight = bmhd.h;
viewport -> RasInfo = ri;
gotheader = 1;
break;
}
case CMAP: {
register UBYTE *ctable;
register UWORD *cmap;
if (!(ctable = AllocMem (ch.chunksize, NULL)))
ackphft ("EA colortable alloc failed.");
fread (ctable, (int) ch.chunksize, 1, fd);
if (!(cmap = AllocMem (ch.chunksize * 2 / 3, NULL)))
ackphft ("Colormap alloc failed.");
for (i = n = 0; n < ch.chunksize; i++, n+=3)
cmap[i] = ((ctable[n] >> 4) << 8) +
((ctable[n+1] >> 4) << 4) +
( ctable[n+2] >> 4);
if ((1 << bmhd.nplanes) != i)
puts ("Warning: Colormap not sized to nplanes, hope it's HAM.");
viewport -> ColorMap = GetColorMap ((long) i);
LoadRGB4 (viewport, cmap, (long) i);
FreeMem (cmap, ch.chunksize * 2 / 3);
FreeMem (ctable, ch.chunksize);
gotcmap = 1;
break;
}
case CAMG:
/* Use subtype as a temporary buffer */
fread (&subtype, (int) ch.chunksize, 1, fd);
viewport -> Modes = (UWORD) (subtype & 0xffff);
gotcamg = 1;
break;
case BODY:
if (!gotheader || !gotcmap)
ackphft ("BODY before BMHD or CMAP.");
loadbitmap (fd, viewport, &bmhd);
break;
case CRNG:
case GRAB:
case DEST:
case SPRT:
case DPPV: /* Anyone know what this one is for? */
skipchunk (fd, ch.chunksize);
break;
default:
printf ("Unrecognized chunk: 0x%lx\n", ch.TYPE);
skipchunk (fd, ch.chunksize);
}
formsize -= ch.chunksize;
if (ch.chunksize & 1) { /* Odd length chunk */
formsize --;
fseek (fd, 1L, 1);
}
}
/* Post-processing in case of lack of CAMG chunk */
if (!gotcamg) {
if (bmhd.w > 370) /* Arbitrary limit */
viewport -> Modes |= HIRES;
if (bmhd.h > 256)
viewport -> Modes |= LACE;
}
tmp = viewport;
viewport = NULL;
return (tmp);
}
loadbitmap (fd, vp, header)
FILE *fd;
struct ViewPort *vp;
struct BitMapHeader *header;
{
register struct BitMap *bm;
register int i, n;
int plane_offset = 0;
bm = vp -> RasInfo -> BitMap;
if (header->Compression != cmpNone &&
header->Compression != cmpByteRun1)
ackphft ("Unrecognized compression technique.");
for (i=0; i < bm->Depth; i++)
if (!(bm -> Planes[i] = AllocRaster ((long) vp -> DWidth,
(long) vp -> DHeight)))
ackphft ("Bitplane allocation failed.");
for (i=0; i < bm->Rows; i++) {
for (n=0; n < bm->Depth; n++) {
/*- - - - - - - - - - -*/
if (!header->Compression) { /* No compression */
if (!fread (bm -> Planes[n] + plane_offset,
bm -> BytesPerRow, 1, fd))
ackphft ("Failure in BODY read.");
} else {
int so_far;
register UBYTE *dest = bm -> Planes[n] + plane_offset;
char len;
/*
* Note: All file I/O after this point is assumed to be sucessful.
* This is clearly a poor assumption, but it saves on typing.
* And besides, putting the checking in is simple :-) :-).
*/
so_far = bm -> BytesPerRow;
while (so_far > 0) {
if ((len = getc (fd)) >= 0) { /* Literal byte copy */
so_far -= ++len;
fread (dest, len, 1, fd);
dest += len;
} else if ((UBYTE) len == 128) /* NOP */
;
else if (len < 0) { /* Replication count */
UBYTE byte;
len = -len + 1;
so_far -= len;
byte = getc (fd);
while (--len >= 0)
*dest++ = byte;
}
}
if (so_far)
ackphft ("Compression quite screwed up.");
}
/*- - - - - - - - - - -*/
}
plane_offset += bm -> BytesPerRow;
}
}
getchunkheader (fd, header)
FILE *fd; /* File descriptor (that's what 'fd' stands for) */
struct ChunkHeader *header;
{
return (fread (header, sizeof (*header), 1, fd));
}
getsubtype (fd, type)
FILE *fd;
long *type;
{
/* !! NOT PORTABLE !! */
return (fread (type, sizeof (*type), 1, fd));
}
skipchunk (fd, size)
FILE *fd;
long size;
{
fseek (fd, size, 1);
}
/*
* This function assumes the existence of the global variable viewport, which
* is a pointer to a working ViewPort structure. This is to allow graceful
* cleanup of allocated resources in case of an exceptional failure.
*/
freepict ()
{
register struct BitMap *bm;
register int i;
if (viewport) {
if (viewport -> RasInfo) {
/*- - - - - - - - - - -*/
if (bm = viewport -> RasInfo -> BitMap) {
for (i=0; i < bm->Depth; i++)
if (bm -> Planes[i])
FreeRaster (bm -> Planes[i],
(long) viewport -> DWidth,
(long) viewport -> DHeight);
FreeMem (bm, (long) sizeof (*bm));
}
/*- - - - - - - - - - -*/
FreeMem (viewport -> RasInfo,
(long) sizeof (struct RasInfo));
}
if (viewport -> ColorMap)
FreeColorMap (viewport -> ColorMap);
FreeVPortCopLists (viewport);
FreeMem (viewport, (long) sizeof (*viewport));
viewport = NULL;
}
}
closeviewport (vp)
struct ViewPort *vp;
{
viewport = vp;
freepict ();
}
/*
* Premature termination routine.
*/
ackphft (str)
char *str;
{
freepict ();
die (str);
}